home *** CD-ROM | disk | FTP | other *** search
- /*
- * Copyright (C) 1992, 1993, 1994, Silicon Graphics, Inc.
- * All Rights Reserved.
- *
- * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
- * the contents of this file may not be disclosed to third parties, copied or
- * duplicated in any form, in whole or in part, without the prior written
- * permission of Silicon Graphics, Inc.
- *
- * RESTRICTED RIGHTS LEGEND:
- * Use, duplication or disclosure by the Government is subject to restrictions
- * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
- * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
- * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
- * rights reserved under the Copyright Laws of the United States.
- */
- /***************************************************************************
- *
- * BZ - Multiplayer tank game - collision routines.
- *
- * $Id: bzcollide.c,v 1.4 1993/08/11 19:46:01 adele Exp $
- *
- * Chris Fouts - Silicon Graphics, Inc.
- * October, 1991
- **************************************************************************/
- #include <stdio.h>
- #include <math.h>
- #include "bz.h"
- #include "bzcollide.h"
-
- /* BEGIN PROTOTYPES -S bzcollide.c */
- static int check_rect_to_rect( float self[4][2], float obstacle[4][2] ) ;
- /* END PROTOTYPES -S bzcollide.c */
-
- extern unsigned number_players ;
- extern struct BzMember player[MAXPLAYERS] ;
- extern float obst_x[TOTALOBSTS] ;
- extern float obst_y[TOTALOBSTS] ;
- extern float last_msl_x[] ;
- extern float last_msl_y[] ;
- extern float mine_x ;
- extern float mine_y ;
-
- #define MAX_TANK_COL_DIST 25.0f
- #define MAX_OBST_COL_DIST 30.0f
-
- static char *version_id = "$Id: bzcollide.c,v 1.4 1993/08/11 19:46:01 adele Exp $" ;
-
-
- /*------------------------------------------------------------------------------
- * INTERSECTION_CHECK - checks for the intersection of two lines. One line
- * is defined by the points r0 and r1; the other line is defined by the
- * points r2 and r3.
- *
- * Line 1 is defined by: Pt = r0 + s * ( r1 - r0 ) ; 0 <= s <= 1
- * Line 2 is defined by: Pt = r2 + t * ( r3 - r2 ) ; 0 <= t <= 1
- *
- * Set the two equal, solve for s and t. If s and t are both between
- * 0 and 1 (inclusive), the lines intersect. Return 1 if the lines
- * intersect, 0 otherwise.
- *----------------------------------------------------------------------------*/
- int intersection_check(
- float r0[2],
- float r1[2],
- float r2[2],
- float r3[2],
- float *s
- )
- {
- float denom ;
- float denom1 ;
- float denom2 ;
- float ns, nt ;
- float dx10, dy10 ;
- float dx20, dy20 ;
- float dx32, dy32 ;
-
- dx10 = r1[0] - r0[0] ;
- dy10 = r1[1] - r0[1] ;
-
- dx20 = r2[0] - r0[0] ;
- dy20 = r2[1] - r0[1] ;
-
- dx32 = r3[0] - r2[0] ;
- dy32 = r3[1] - r2[1] ;
-
- denom1 = dy10 * dx32 ;
- denom2 = dx10 * dy32 ;
-
- /*
- * Fail if lines are parallel.
- */
- if( denom1 == denom2 )
- return( 0 ) ;
-
- denom = denom1 - denom2 ;
-
- ns = dx32 * dy20 - dy32 * dx20 ;
- nt = dx10 * dy20 - dy10 * dx20 ;
-
- /*
- * Fail if s or t will be greater than 1 (s = ns/denom ; t = nt/denom).
- if( ns > denom || nt > denom )
- return( 0 ) ;
- */
-
- /*
- * Fail if s or t are less than 0 (negative, which happens if ns or nt
- * are of different signs than denom) or greater than 1 (if abs(ns) or
- * abs(nt) are greater than abs(denom) ).
- */
- if( denom < 0 ) {
- if( ns > 0 || nt > 0 || ns < denom || nt < denom ) {
- return( 0 ) ;
- }
- }
- else {
- if( ns < 0 || nt < 0 || ns > denom || nt > denom ) {
- return( 0 ) ;
- }
- }
-
- *s = ns / denom ;
-
- return( 1 ) ;
- }
-
-
-
- int check_missile_hit(
- int tank_id,
- unsigned int *obst_id,
- int *side
- )
- {
- int tank ;
- int obst ;
- float self[2][2] ;
- float obstacle[4][2] ;
-
- /*
- * Get missile points.
- */
- self[0][0] = last_msl_x[tank_id] ;
- self[0][1] = last_msl_y[tank_id] ;
- self[1][0] = player[tank_id].msl_x ;
- self[1][1] = player[tank_id].msl_y ;
-
- /*
- * Compare against other tanks.
- */
- for( tank = SELF ; tank < number_players ; tank++ ) {
- if( IS_ALIVE( player[tank] ) ) {
- locate_tank_corner_points( tank, obstacle ) ;
- if( ( *side = check_line_to_rect( self, obstacle, 0 ) ) != 0 ) {
- *obst_id = tank ;
- return( 1 ) ;
- }
- }
- }
-
- /*
- * Compare against obstacles.
- */
- for( obst = CONES ; obst < CUBES ; obst++ ) {
- locate_obstacle_corner_points( obst, obstacle, CONE_COLLISION_INSET ) ;
- if( ( *side = check_line_to_rect( self, obstacle, 1 ) ) != 0 ) {
- *obst_id = obst ;
- return( 2 ) ;
- }
- }
- for( obst = CUBES ; obst < TOTALOBSTS ; obst++ ) {
- locate_obstacle_corner_points( obst, obstacle, 1.0f ) ;
- if( ( *side = check_line_to_rect( self, obstacle, 1 ) ) != 0 ) {
- *obst_id = obst ;
- return( 2 ) ;
- }
- }
-
- return( 0 ) ;
- }
-
-
-
- int check_tank_collision(
- unsigned int tank_id,
- unsigned int *obst_id
- )
- {
- int tank ;
- int obst ;
- float self[4][2] ;
- float obstacle[4][2] ;
-
- /*
- * Get self corner points.
- */
- locate_tank_corner_points( tank_id, self ) ;
-
- /*
- * Compare against other tanks.
- */
- for( tank = SELF ; tank < number_players ; tank++ ) {
- if( tank != tank_id && IS_ALIVE( player[tank] ) &&
- fabsf( player[tank_id].x - player[tank].x ) < MAX_TANK_COL_DIST &&
- fabsf( player[tank_id].y - player[tank].y ) < MAX_TANK_COL_DIST ) {
- locate_tank_corner_points( tank, obstacle ) ;
- if( check_rect_to_rect( self, obstacle ) ) {
- *obst_id = tank ;
- return( 1 ) ;
- }
- }
- }
-
- /*
- * Compare against obstacles.
- */
- for( obst = CONES ; obst < CUBES ; obst++ ) {
- if( fabsf( player[tank_id].x - obst_x[obst] ) < MAX_OBST_COL_DIST &&
- fabsf( player[tank_id].y - obst_y[obst] ) < MAX_OBST_COL_DIST ) {
- locate_obstacle_corner_points( obst, obstacle, 1.0f ) ;
- if( check_rect_to_rect( self, obstacle ) ) {
- *obst_id = obst ;
- return( 2 ) ;
- }
- }
- }
- for( obst = CUBES ; obst < TOTALOBSTS ; obst++ ) {
- if( fabsf( player[tank_id].x - obst_x[obst] ) < MAX_OBST_COL_DIST &&
- fabsf( player[tank_id].y - obst_y[obst] ) < MAX_OBST_COL_DIST ) {
- locate_obstacle_corner_points( obst, obstacle, 1.0f ) ;
- if( check_rect_to_rect( self, obstacle ) ) {
- *obst_id = obst ;
- return( 2 ) ;
- }
- }
- }
-
- return( 0 ) ;
- }
-
-
-
- void locate_tank_corner_points(
- int tank_id,
- float pt[4][2]
- )
- {
- float x ;
- float y ;
- float w ;
- float l ;
- float wc ;
- float ws ;
- float lc ;
- float ls ;
-
- x = player[tank_id].x ;
- y = player[tank_id].y ;
- w = 5.0f ;
- l = 10.0f ;
-
- wc = COSINE( player[tank_id].head ) ;
- ws = SINE( player[tank_id].head ) ;
- lc = l * wc ;
- ls = l * ws ;
- wc *= w ;
- ws *= -w ;
-
- pt[0][0] = x + wc + ls ;
- pt[0][1] = y + ws + lc ;
-
- pt[1][0] = x - wc + ls ;
- pt[1][1] = y - ws + lc ;
-
- pt[2][0] = x - wc - ls ;
- pt[2][1] = y - ws - lc ;
-
- pt[3][0] = x + wc - ls ;
- pt[3][1] = y + ws - lc ;
- }
-
-
-
- void locate_obstacle_corner_points(
- int obst_id,
- float pt[4][2],
- float scaling
- )
- {
- float x ;
- float y ;
- float dx ;
- float dy ;
-
- x = obst_x[obst_id] ;
- y = obst_y[obst_id] ;
-
- /*
- * Scaling factor in order to model slope of cones at missile height.
- */
- dx = 10.0f * scaling ;
- dy = 10.0f * scaling ;
-
- pt[0][0] = x - dx ;
- pt[0][1] = y + dy ;
-
- pt[1][0] = x + dx ;
- pt[1][1] = y + dy ;
-
- pt[2][0] = x + dx ;
- pt[2][1] = y - dy ;
-
- pt[3][0] = x - dx ;
- pt[3][1] = y - dy ;
- }
-
-
-
- static int check_rect_to_rect(
- float self[4][2],
- float obstacle[4][2]
- )
- {
- int s0 ;
- int s1 ;
- int o0 ;
- int o1 ;
- float s ;
-
- for( s0 = 0 ; s0 < 4 ; s0++ ) {
- s1 = ( s0 + 1 ) % 4 ;
- for( o0 = 0 ; o0 < 4 ; o0++ ) {
- o1 = ( o0 + 1 ) % 4 ;
- if( intersection_check( self[s0], self[s1],
- obstacle[o0], obstacle[o1], &s ) )
- return( 1 ) ;
- }
- }
-
- return( 0 ) ;
- }
-
-
-
- int check_line_to_rect(
- float self[2][2],
- float obstacle[4][2],
- int closest
- )
- {
- int o0 ;
- int o1 ;
- int jmin = 0 ;
- float s ;
- float smin ;
-
- for( o0 = 0 ; o0 < 4 ; o0++ ) {
- o1 = ( o0 + 1 ) % 4 ;
- if( intersection_check( self[0], self[1],
- obstacle[o0], obstacle[o1], &s ) )
- if( !closest ) {
- return( o0 + 1 ) ;
- }
- else if( jmin == 0 ) {
- jmin = o0 + 1 ;
- smin = s ;
- }
- else if( s < smin ) {
- jmin = o0 + 1 ;
- }
- }
-
- return( jmin ) ;
- }
-
-
-
- int check_mine_hit(
- unsigned int *enemy_id,
- float radius_2
- )
- {
- int tank ;
- float dx ;
- float dy ;
-
- for( tank = ENEMY ; tank < number_players ; tank++ ) {
- if( player[tank].team == NEUTRAL_TEAM ||
- player[tank].team != player[SELF].team ) {
- dx = mine_x - player[tank].x ;
- dy = mine_y - player[tank].y ;
- if( dx*dx + dy*dy < radius_2 ) {
- *enemy_id = tank ;
- return( 1 ) ;
- }
- }
- }
-
- dx = mine_x - player[SELF].x ;
- dy = mine_y - player[SELF].y ;
- if( dx*dy + dy*dy < radius_2 ) {
- *enemy_id = SELF ;
- return( 1 ) ;
- }
-
- return( 0 ) ;
- }
-
-
-
- int id_tank( void )
- {
- int tank ;
- int obst ;
- int closest_tank = 0 ;
- float self[2][2] ;
- float obstacle[4][2] ;
- float dist ;
- float min_dist = 1.e30f ;
-
- /*
- * Get line representing line o' sight.
- */
- self[0][0] = player[SELF].x ;
- self[0][1] = player[SELF].y ;
- self[1][0] = player[SELF].x + 100000.f * SINE( player[SELF].head ) ;
- self[1][1] = player[SELF].x + 100000.f * COSINE( player[SELF].head ) ;
-
- /*
- * Compare against other tanks.
- */
- for( tank = ENEMY ; tank < number_players ; tank++ ) {
- if( IS_ALIVE( player[tank] ) ) {
- locate_tank_corner_points( tank, obstacle ) ;
- if( check_line_to_rect( self, obstacle, 0 ) ) {
- dist = ( player[tank].x - player[SELF].x ) *
- ( player[tank].x - player[SELF].x ) +
- ( player[tank].y - player[SELF].y ) *
- ( player[tank].y - player[SELF].y ) ;
- if( dist < min_dist ) {
- min_dist = dist ;
- closest_tank = tank ;
- }
- }
- }
- }
-
- /*
- * Compare against obstacles.
- */
- for( obst = CONES ; obst < CUBES ; obst++ ) {
- locate_obstacle_corner_points( obst, obstacle, 0.8375f ) ;
- if( check_line_to_rect( self, obstacle, 0 ) ) {
- dist = ( obst_x[obst] - player[SELF].x ) *
- ( obst_x[obst] - player[SELF].x ) +
- ( obst_y[obst] - player[SELF].y ) *
- ( obst_y[obst] - player[SELF].y ) ;
- if( dist < min_dist ) {
- return( 0 ) ;
- }
- }
- }
- for( obst = CUBES ; obst < TOTALOBSTS ; obst++ ) {
- locate_obstacle_corner_points( obst, obstacle, 1.0f ) ;
- if( check_line_to_rect( self, obstacle, 0 ) ) {
- dist = ( obst_x[obst] - player[SELF].x ) *
- ( obst_x[obst] - player[SELF].x ) +
- ( obst_y[obst] - player[SELF].y ) *
- ( obst_y[obst] - player[SELF].y ) ;
- if( dist < min_dist ) {
- return( 0 ) ;
- }
- }
- }
-
- return( closest_tank ) ;
- }
-
-
-
-